/**
 * 简易观察者模式
 * 
 */

//  设置某个事件的最大数组上限
 const MAX_LISTENERS=100



 /**
 * 固定某些特殊事件的事件名
 * 
 * message_send_time_out  发送信息超时/失败
 * message_send_success   发送消息成功(消息确认)
 * message_new_received    新消息接收成功
 * 
 */

 export const constEventName={

    message_client_send:'message_client_send', //消息发送
    message_send_time_out:'message_send_time_out',
    message_send_success:'message_send_success',
    message_new_received:'message_new_received',
    
 }

 
let event=new Function()

/**
 * 用来存储所有事件 key:String, value:Array{function} 
 * 
 */
event._events=new Object()

/**
 * 
 * 
 */
event.$on=(name,cb)=>{
   if(!name||typeof name!=='string'||typeof cb!=='function') return
   if(!this._events[name]) this._events[name]=[].push(cb)
   else if(this._events[name].length>=MAX_LISTENERS){
       console.info('Exceeded the maximum limit')
       return
   }
   else this._events[name]=this._events[name].push(cb)
}

event.$emit=(name,cb)=>{
    if(!name||typeof name!=='string') return
    if(!this._events[name]){
        cb&&cb()
        return
    }
    this._events[name].reduce((prev,cur)=>cur&&cur.call(this))
}

event.$off=(name,cb)=>{
   if(!name||typeof name!=='string'||!this._events[name]) return
   if(!cb) delete this._events[name] 
   else{
       let i=this._events[name].indexOf(cb)
       if(i>-1) this._events[name].splice(i,1)
   } 
}

/**
 * 此时要改写cb,执行完后调用$off
 * 
 */
event.$once=(name,cb)=>{
   if(!name||typeof name!=='string'||typeof cb!=='function') return
   let on=()=>{
       this.$off(name,cb)
       cb&&cb.apply(this,arguments)
   }
   this.$on(name,on)
}




export class Event{

   constructor(){
       this._events=new Object()
   }

   $on(name,cb){
    if(!name||typeof name!=='string'||(typeof cb!=='function'&&!Array.isArray(cb))) return
    if(!this._events[name]){
        if(Array.isArray(cb)){
            this._events[name]=cb
            return
        }
        let arr=new Array() 
        arr.push(cb)
        this._events[name]=arr
    }    
    else if(this._events[name].length>=MAX_LISTENERS){
        console.info('Exceeded the maximum limit')
        return
    }
    else Array.isArray(cb)?this._events[name].concat(cb):this._events[name].push(cb)
   }

   $emit(name,cb){
    if(!name||typeof name!=='string') return
    if(!this._events[name]){
        cb&&cb()
        return
    }
    this._events[name].forEach(cur=>cur&&cur.call(this))
   }

   $off(name,cb){
    if(!name||typeof name!=='string'||!this._events[name]) return
    if(!cb) delete this._events[name] 
    else{
        // 暂无法比较两个function是否相同，总是不同
        let i=this._events[name].indexOf(cb)
        if(i>-1) this._events[name].splice(i,1)
    } 
   }

   $once(name,cb){
    if(!name||typeof name!=='string'||typeof cb!=='function') return
    let on=()=>{
        this.$off(name,cb)
        cb&&cb.apply(this,arguments)
    }
    this.$on(name,on)
  }

}


